package com.bzframework.project.api.service;

import com.bzframework.pro.api.core.manager.ApiSupportManager;
import com.bzframework.pro.api.core.provider.ApiSupport;
import com.bzframework.pro.authorize.token.UserToken;
import com.bzframework.project.api.configuration.ProtocolProperties;
import com.bzframework.project.api.entity.OpenApiEntity;
import com.bzframework.project.api.entity.OpenApiProtocolEntity;
import com.bzframework.project.api.model.request.ProtocolRequest;
import lombok.RequiredArgsConstructor;
import org.hswebframework.ezorm.rdb.mapping.defaults.SaveResult;
import org.hswebframework.web.bean.FastBeanCopier;
import org.hswebframework.web.crud.service.GenericReactiveCrudService;
import org.hswebframework.web.exception.BusinessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Mono;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Author bingzhong
 * @Date 2025/3/3 15:52
 * @Description
 */
@Service
@RequiredArgsConstructor
public class OpenApiProtocolService extends GenericReactiveCrudService<OpenApiProtocolEntity, String> {

    private final ApiSupportManager apiSupportManager;

    private final ProtocolProperties protocolProperties;

    @Transactional
    public Mono<SaveResult> loadApiSupportJar(ProtocolRequest protocolRequest, UserToken userToken) {
        String location = protocolRequest.getLocation();
        Path apiStoragePath = Paths.get(protocolProperties.getBaseStoragePath(), location);
        String id = protocolRequest.getId();
        // 修改
        if (StringUtils.hasText(id)) {
            return this.createQuery()
                       .where(OpenApiProtocolEntity::getLocation, location)
                       .fetchOne()
                       .switchIfEmpty(Mono.error(new BusinessException("api 不存在")))
                       .flatMap(protocol -> {
                           return apiSupportManager.loadJar(protocolRequest.getId(), apiStoragePath.toFile().getAbsolutePath())
                                   .collectList()
                                   .flatMap(apiSupports -> {
                                       OpenApiProtocolEntity protocolEntity = FastBeanCopier.copy(protocolRequest, OpenApiProtocolEntity.class);
                                       return this.save(protocolEntity);
                                   })
                                   .doFinally(signalType -> {
                                       // 删除旧文件
                                       Path oldApiStoragePath = Paths.get(protocolProperties.getBaseStoragePath(), protocol.getLocation());
                                       oldApiStoragePath.toFile().delete();
                                   });
                       });
        }
        // 新增
        OpenApiProtocolEntity openApiProtocolEntity = FastBeanCopier.copy(protocolRequest, OpenApiProtocolEntity.class);
        return this.save(openApiProtocolEntity)
                   .flatMap(saveResult -> apiSupportManager.loadJar(openApiProtocolEntity.getId(), apiStoragePath.toFile().getAbsolutePath())
                                                           .then(Mono.just(saveResult)));
    }

    public Mono<Integer> removeProtocolById(String id) {
        return Mono.defer(() -> {
            apiSupportManager.remove(id);
            return this.deleteById(id);
        });
    }

    /**
     * 校验api是否已经存在
     *
     * @param openApiList jar提供的api
     * @return jar提供的api
     */
    private Mono<List<ApiSupport>> validateApiExist(List<ApiSupport> openApiList) {
        List<String> openApiIds = openApiList
                .stream()
                .map(ApiSupport::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        return this.createQuery()
                   .in(OpenApiEntity::getId, openApiIds)
                   .fetch()
                   .doOnNext(openApiEntity -> {
                       throw new BusinessException("api id 已存在,请设置一个唯一的id");
                   })
                   .then(Mono.just(openApiList));
    }
}
